package com.sheng.project.utils;

import cn.hutool.core.lang.Assert;
import com.sheng.project.constant.AsyncStatusEnum;
import com.sheng.project.model.async.AsyncProcess;
import com.sheng.project.repository.AsyncProcessRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;

import java.util.function.Function;

/**
 * @author by ls
 * @date 2023/8/21
 */
@Component
public class ThreadUtil {

    private static AsyncProcessRepository repository;

    /**
     * 根据线程 ID 查询线程
     *
     * @param threadId 线程 ID
     * @return Thread
     */
    public static Thread findThread(Long threadId) {
        Thread thread = null;
        ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
        if (threadGroup != null) {
            Thread[] threads = new Thread[threadGroup.activeCount() << 1];
            int count = threadGroup.enumerate(threads, true);
            for (int i = 0; i < count; i++) {
                if (threadId == threads[i].getId()) {
                    thread = threads[i];
                }
            }
        }
        return thread;
    }

    /**
     * 根据线程 ID,停止线程的运行
     *
     * @param threadId 线程 ID
     * @return 返回停止结果
     */
    public static boolean stopThread(Long threadId) {
        if (threadId != null) {
            Thread thread = findThread(threadId);
            Assert.isNull(thread, "线程不存在或已停止");
            thread.interrupt();
            return true;
        }
        return false;
    }

    /**
     * 异步执行任务
     *
     * @param taskExecutor 线程池
     * @param function     执行业务逻辑
     * @return 执行信息
     */
    public static AsyncProcess async(TaskExecutor taskExecutor, Function<Object, String> function) {
        // 初始化参数
        AsyncProcess asyncProcess = new AsyncProcess();
        asyncProcess.setStatus(AsyncStatusEnum.WAIT.name());
        repository.saveAndFlush(asyncProcess);
        taskExecutor.execute(() -> {
            try {
                // 线程 ID
                long threadId = Thread.currentThread().getId();
                // 线程名称
                String threaName = Thread.currentThread().getName();
                // 任务开始时间
                long start = System.currentTimeMillis();
                asyncProcess.setThreadId(threadId);
                asyncProcess.setThreadName(threaName);
                asyncProcess.setStart(start);
                asyncProcess.setStatus(AsyncStatusEnum.PROCESS.name());
                // 执行任务，保存任务执行的返回信息
                String additionalInfo = function.apply(asyncProcess);
                asyncProcess.setAdditionalInfo(additionalInfo);
                repository.saveAndFlush(asyncProcess);
            } catch (Exception e) {
                // 保存异常信息
                asyncProcess.setErrMsg(e.getMessage());
                asyncProcess.setStatus(AsyncStatusEnum.EXCEPTION.name());
                repository.saveAndFlush(asyncProcess);
            }
            long end = System.currentTimeMillis();
            asyncProcess.setEnd(end);
            asyncProcess.setStatus(AsyncStatusEnum.SUCCESS.name());
            // 任务结束
            repository.saveAndFlush(asyncProcess);
        });
        return asyncProcess;
    }

    @Autowired
    public void setRepository(AsyncProcessRepository repository) {
        ThreadUtil.repository = repository;
    }
}
